#include <sys_config.h>
#include <types.h>
#include <osal/osal.h>
#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <hld/hld_dev.h>
#include <hld/dmx/dmx_dev.h>
#include <hld/dmx/dmx.h>
#include <hld/decv/vdec_driver.h>
#ifndef NEW_DEMO_FRAME
#include <api/libpub29/lib_hde.h>
#include <api/libpub29/lib_pub27.h>
#else
#include <api/libpub/lib_hde.h>
#endif
//#include <api/libtsi/si_epg.h>

#include <api/libosd/osd_lib.h>

#include "osdobjs_def.h"
#include "images.id"
#include "string.id"
#include "osd_config.h"

#include "menus_root.h"
#include "win_com.h"
#include "win_com_popup.h"
#include "win_com_list.h"
#include "win_signalstatus.h"
#include "win_signal.h"

#include "control.h"
/*******************************************************************************
*	Objects definition
*******************************************************************************/
extern CONTAINER	g_win_progdetail;
extern TEXT_FIELD txt_progname;

#if (SYS_PROJECT_FE == PROJECT_FE_DVBS || SYS_PROJECT_FE == PROJECT_FE_DVBS2)
extern TEXT_FIELD txt_satname;
#endif

extern TEXT_FIELD txt_tpinfo;
extern TEXT_FIELD txt_pidinfo;
extern TEXT_FIELD txt_string1;
extern TEXT_FIELD txt_string2;
extern TEXT_FIELD txt_string3;
extern TEXT_FIELD txt_string4;
//volatile BOOL g_b_is_open_sfu = FALSE;
#ifndef SD_UI
#define W_L	155//240
#define W_T	100//100
#define W_W	698//490
#define W_H	330//230

#define TXT_T (W_T + 20 + 4)
#define TXT_W 390//460
#define TXT_H  44
#define TXT_STR_W  260
#define TXT_STR_L (W_L + 30)
#define TXT_L (TXT_STR_L + TXT_STR_W)

#define SIGNAL_OFFSET 20
#define SIGNAL_L (W_L + SIGNAL_OFFSET)
#define SIGNAL_T (TXT_T + TXT_H*4 + SIGNAL_OFFSET - 8)
#define SIGNAL_W (W_W - SIGNAL_OFFSET *2)
#define SIGNAL_H (W_T + W_H - SIGNAL_T)

#else
#define W_L	58//240
#define W_T	60//100
#define W_W	490//490
#define W_H	240//230

#define TXT_T (W_T + 10)
#define TXT_W 300//460
#define TXT_H  30
#define TXT_STR_W  130
#define TXT_STR_L (W_L + 16)
#define TXT_L (TXT_STR_L + TXT_STR_W)

#define SIGNAL_OFFSET 8
#define SIGNAL_L (W_L + SIGNAL_OFFSET)
#define SIGNAL_T (TXT_T + TXT_H*4 + SIGNAL_OFFSET - 8)
#define SIGNAL_W (W_W - SIGNAL_OFFSET *2)
#define SIGNAL_H (W_T + W_H - SIGNAL_T)
#endif

#define PROG_WIN_SH_IDX         WSTL_POP_WIN_01_8BIT
#define TXT_INFO_IDX            WSTL_TEXT_30_8BIT //WSTL_TEXT_28_8BIT//WSTL_TEXT_04

static VACTION win_progdetail_keymap(POBJECT_HEAD pObj, UINT32 key);
static PRESULT win_progdetail_callback(POBJECT_HEAD pObj, VEVENT event, UINT32 param1, UINT32 param2);
#define LDEF_TXT(root,varTxt,nxtObj,l,t,w,h,str)		\
    DEF_TEXTFIELD(varTxt,root,nxtObj,C_ATTR_ACTIVE,0, \
    0,0,0,0,0, l,t,w,h, TXT_INFO_IDX,TXT_INFO_IDX,TXT_INFO_IDX,TXT_INFO_IDX,   \
    NULL,NULL,  \
    C_ALIGN_LEFT | C_ALIGN_VCENTER, 0,0,0,str)
#define LDEF_STRTXT(root,varTxt,nxtObj,l,t,w,h,strID)		\
    DEF_TEXTFIELD(varTxt,root,nxtObj,C_ATTR_ACTIVE,0, \
    0,0,0,0,0, l,t,w,h, TXT_INFO_IDX,TXT_INFO_IDX,TXT_INFO_IDX,TXT_INFO_IDX,   \
    NULL,NULL,  \
    C_ALIGN_LEFT | C_ALIGN_VCENTER, 0,0,strID,NULL)

#define LDEF_WIN(varWnd,nxtObj,l,t,w,h,sh,nextObj,focusID)		\
    DEF_CONTAINER(varWnd,NULL,NULL,C_ATTR_ACTIVE,0, \
	    0,0,0,0,0, l,t,w,h, sh,sh,sh,sh,   \
	    win_progdetail_keymap,win_progdetail_callback,  \
	    nextObj, focusID,1)
	    
#if (SYS_PROJECT_FE == PROJECT_FE_DVBS || SYS_PROJECT_FE == PROJECT_FE_DVBS2)
LDEF_TXT(&g_win_progdetail,txt_progname,&txt_satname,TXT_L,(TXT_T + TXT_H * 0),TXT_W,TXT_H,display_strs[0])
LDEF_TXT(&g_win_progdetail,txt_satname,&txt_tpinfo,TXT_L,(TXT_T + TXT_H * 1),TXT_W,TXT_H,display_strs[1])
LDEF_TXT(&g_win_progdetail,txt_tpinfo,&txt_pidinfo,TXT_L,(TXT_T + TXT_H * 2),TXT_W,TXT_H,display_strs[2])
LDEF_TXT(&g_win_progdetail,txt_pidinfo,&txt_string1,TXT_L,(TXT_T + TXT_H * 3),TXT_W,TXT_H,display_strs[3])
LDEF_STRTXT(&g_win_progdetail,txt_string1,&txt_string2,TXT_STR_L,(TXT_T + TXT_H * 0),TXT_STR_W,TXT_H,RS_SYSTEM_TIMERSET_CHANNEL)
LDEF_STRTXT(&g_win_progdetail,txt_string2,&txt_string3,TXT_STR_L,(TXT_T + TXT_H * 1),TXT_STR_W,TXT_H,RS_INFO_SATELLITE)
LDEF_STRTXT(&g_win_progdetail,txt_string3,&txt_string4,TXT_STR_L,(TXT_T + TXT_H * 2),TXT_STR_W,TXT_H,RS_INFO_TRANSPONDER)
LDEF_TXT(&g_win_progdetail,txt_string4,NULL,TXT_STR_L,(TXT_T + TXT_H * 3),TXT_STR_W,TXT_H,display_strs[4])
#else
LDEF_TXT(&g_win_progdetail,txt_progname,&txt_tpinfo,TXT_L,(TXT_T + TXT_H * 0),TXT_W,TXT_H,display_strs[0])
LDEF_TXT(&g_win_progdetail,txt_tpinfo,&txt_pidinfo,TXT_L,(TXT_T + TXT_H * 1),TXT_W,TXT_H,display_strs[1])
LDEF_TXT(&g_win_progdetail,txt_pidinfo,&txt_string1,TXT_L,(TXT_T + TXT_H * 2),TXT_W,TXT_H,display_strs[2])
LDEF_STRTXT(&g_win_progdetail,txt_string1,&txt_string3,TXT_STR_L,(TXT_T + TXT_H * 0),TXT_STR_W,TXT_H,RS_SYSTEM_TIMERSET_CHANNEL)
LDEF_STRTXT(&g_win_progdetail,txt_string3,&txt_string4,TXT_STR_L,(TXT_T + TXT_H * 1),TXT_STR_W,TXT_H,RS_INFO_TRANSPONDER)
LDEF_TXT(&g_win_progdetail,txt_string4,NULL,TXT_STR_L,(TXT_T + TXT_H * 2),TXT_STR_W,TXT_H,display_strs[3])
#endif

LDEF_WIN(g_win_progdetail,NULL,W_L,W_T,W_W,W_H,PROG_WIN_SH_IDX,&txt_progname,1)

void info_load(void);
/*******************************************************************************
*	function definition
*******************************************************************************/
static VACTION win_progdetail_keymap(POBJECT_HEAD pObj, UINT32 key)
{
	VACTION act;
	
	switch(key)
	{
	case V_KEY_MENU:
	case V_KEY_INFOR:
	case V_KEY_EXIT:
		act = VACT_CLOSE;
		break;			
	default:	
		act = VACT_PASS;
		break;
	}
	
	return act;
}

BOOL check_magic_key_firmware_info(UINT32 code)
{
	static UINT8 magic_key[] = { V_KEY_5, V_KEY_6,V_KEY_5,V_KEY_6,V_KEY_5 };
	static int key_cnt = 0;
#ifndef SUPPORT_CAS9
	if (magic_key[key_cnt++] == code)
	{
		if (key_cnt == (int)(sizeof(magic_key)/sizeof(UINT8)))
		{
			key_cnt = 0;
			return TRUE;
		}
		else
			return FALSE;
	}
#endif	
	key_cnt = 0;
	return FALSE;
}

static char info[500];
void show_firmware_info()
{
#ifndef _CAS9_CA_ENABLE_
    char *p = info;
    UINT8 back_save, i;
    UINT32 reg_temp,reg_addr;
    UINT16 strlen;

    STRCPY(p, (const char *)get_sdk_ver());
    strlen = STRLEN(info);
    p = info + strlen;

    STRCPY(p, (const char *)get_app_ver());
    strlen = STRLEN(info);
    p = info + strlen;

    STRCPY(p,(const char *)get_core_ver());
    strlen = STRLEN(info);
    p = info + strlen;

    sprintf(p, "0xb8000074/7c: 0x%08x 0x%08x\n", 
    *((volatile UINT32 *)0xb8000074), *((volatile UINT32 *)0xb800007c));
    strlen = STRLEN(info);
    p = info + strlen;

    reg_temp = *((volatile UINT32 *)0xb8018504);
    sprintf(p, "0xb8018504: 0x%08x\n", reg_temp);
    strlen = STRLEN(info);
    p = info + strlen;

    reg_addr = 0xb8001270;
    i=0;
    while(reg_addr <= 0xb800129c)
    {
        if(i%4 == 0)
        {
            sprintf(p, "0x%x: ", reg_addr);
            strlen = STRLEN(info);
            p = info + strlen;
        }

        reg_temp = *((volatile UINT32 *)(reg_addr));
        sprintf(p, "0x%08x ",reg_temp);
        strlen = STRLEN(info);
        p = info + strlen;
        reg_addr += 4;
        i++;
        if(i%4 == 0)
        {
            sprintf(p, "\n");
            strlen = STRLEN(info);
            p = info + strlen;
        }
    }
    win_compopup_init(WIN_POPUP_TYPE_OK);
    win_compopup_set_msg_ext(info, NULL, 0);
    win_compopup_set_frame(GET_MID_L(900), GET_MID_T(500), 900, 500);
    win_compopup_open_ext(&back_save);
#endif	
}


static PRESULT win_progdetail_callback(POBJECT_HEAD pObj, VEVENT event, UINT32 param1, UINT32 param2)
{	
	PRESULT ret = PROC_PASS;
    UINT32  vkey;
    static int input_num = 0;
	switch(event)
	{
	case EVN_PRE_OPEN:
        #ifdef SUPPORT_CAS7
	restore_ca_msg_when_exit_win();
        #endif
        api_inc_wnd_count();
		info_load();
#if (CC_ON==1)
		cc_vbi_show_on(FALSE);
#endif
		break;
	case EVN_POST_OPEN:
		//win_minisignal_open(pObj);
		win_minisignal_open_ex(pObj,SIGNAL_L,SIGNAL_T);
        win_signal_refresh();
		break;
	case EVN_MSG_GOT:
		if(CTRL_MSG_SUBTYPE_STATUS_SIGNAL == param1)
			win_signal_refresh(); 
        else if(CTRL_MSG_SUBTYPE_CMD_PIDCHANGE == param1)
        {
            info_load();
            OSD_DrawObject((POBJECT_HEAD)&txt_pidinfo,C_UPDATE_ALL);
        }
        else if(CTRL_MSG_SUBTYPE_STATUS_AUDIO_TYPE_UPDATE == param1)
        {
            info_load();
            OSD_DrawObject((POBJECT_HEAD)&txt_pidinfo,C_UPDATE_ALL);
        }

		break;
	case EVN_PRE_CLOSE:
		break;
	case EVN_POST_CLOSE:
		win_minisignal_restore();
		win_signal_close();		
        api_dec_wnd_count();
#ifdef ENABLE_ATSC_CC_BY_VBI
			cc_vbi_show_on(TRUE);
#endif
        #ifdef SUPPORT_CAS9
			restore_ca_msg_when_exit_win();
        #endif
		#ifdef SUPPORT_CAS7
		win_ca_mmi_check();
		#endif	
		break;

   	case EVN_UNKNOWNKEY_GOT:

        ap_hk_to_vk(0,param1,&vkey);
		if (factorytest_check_magic_key_diag(vkey))
		{
			ap_clear_all_menus();
			ap_send_msg(CTRL_MSG_SUBTYPE_CMD_ENTER_ROOT, (UINT32)&win_diag, TRUE);
		}

         if(check_magic_key_firmware_info(vkey))
         {
            if (sys_ic_get_chip_id() >= ALI_S3602F)
                show_firmware_info();
         }

#ifdef SFU_TEST_SUPPORT
        //libc_printf("%s %d\n",__FUNCTION__,vkey);
        if(vkey <= V_KEY_9 && vkey >= V_KEY_0)
        {
            input_num *= 10;
            input_num += vkey;
            if(2008 == input_num)
            {
                 //#define IOBASEADDRRESS  0xB8000000
                 //#if (SYS_CHIP_MODULE == ALI_S3601)
                 //#define EXT_INT_STAT    (IOBASEADDRRESS + 0x30)
                 //#define EXT_INT_MASK    (IOBASEADDRRESS + 0x34)
                 //#elif (SYS_CHIP_MODULE == ALI_S3602)
                 //#define EXT_INT_STAT    (IOBASEADDRRESS + 0x30)
                 //#define EXT_INT_MASK    (IOBASEADDRRESS + 0x38)
                 //#else
                 //#define EXT_INT_STAT    (IOBASEADDRRESS + 0x38)
                 //#define EXT_INT_MASK    (IOBASEADDRRESS + 0x3C)
                 //#endif
                 //disable pan and ir interrupt
                 //*(volatile UINT32*)EXT_INT_MASK = (*(volatile UINT32*)EXT_INT_MASK) & (~0x10080000);
                 //libc_printf("Enter SFU auto test\n");
                 
//                 extern struct pan_device*   g_pan_dev;
//                 pan_close(g_pan_dev);    //Don't need to close panel for diable IR now, because it will case IR no respondence after implement 'stop' command.
//                 g_b_is_open_sfu = TRUE;

                 input_num = 0;
                 SFUTestInit();
                 ap_send_msg(CTRL_MSG_SUBTYPE_CMD_EXIT_ROOT, (UINT32)&g_win_progdetail,FALSE);
            }
        }
        else
        {
            input_num = 0;
        }
#endif		
        break;

	default:
		break;
	}

	return ret;
}
void info_load(void)
{
	char str[50];
	UINT16 audioPID,ttxPID,subtPID;
	UINT32 cur_audio;
	TEXT_FIELD *txt;
	P_NODE p_node;
	T_NODE t_node;
	S_NODE s_node;
    void *freq_str;// freq[20];
    char *FFT, *modulation;
	UINT8 NIM_FFT,NIM_modulation;
	struct nim_device* priv_nim_dev = NULL;
	struct ts_route_info ts_route;
	sys_data_get_curprog_info(&p_node);
	get_tp_by_id(p_node.tp_id,&t_node);
	get_sat_by_id(t_node.sat_id, &s_node);
	
	if(t_node.ft_type == FRONTEND_TYPE_T)
	{
		ts_route_get_by_type(TS_ROUTE_MAIN_PLAY, NULL, &ts_route);
		if(ts_route.nim_id == 0)
			priv_nim_dev = g_nim_dev;
		else if(ts_route.nim_id == 1)
			priv_nim_dev = g_nim_dev2;
		if(priv_nim_dev != NULL)
		{
			if(priv_nim_dev->get_fftmode)
			{
				priv_nim_dev->get_fftmode(priv_nim_dev,&NIM_FFT);
		        t_node.FFT = NIM_FFT;
			}
			if(priv_nim_dev->get_modulation)
			{
				priv_nim_dev->get_modulation(priv_nim_dev,&NIM_modulation);
		        t_node.modulation = NIM_modulation;
			}
		}
	}
	cur_audio = (p_node.cur_audio >= p_node.audio_count) ? 0 : p_node.cur_audio;
	audioPID = p_node.audio_pid[cur_audio];
	ttxPID = p_node.teletext_pid;
	subtPID = p_node.subtitle_pid;
	if(p_node.audio_count == 0)
		sprintf(str,"V %d  No Audio  P %d",p_node.video_pid,p_node.pcr_pid);
	else
	{
		UINT8 str_audio_type[32];

        key_check_ddplus_stream_changed(&audioPID);

		if((audioPID  & 0xE000) == AC3_DES_EXIST)
			STRCPY(str_audio_type, "Dolby D");
        else if((audioPID & 0xE000) == EAC3_DES_EXIST)
			STRCPY(str_audio_type, "Dolby D+");
        else if((audioPID & 0xE000) == AAC_DES_EXIST)
			STRCPY(str_audio_type, "AAC");
		else if((audioPID & 0xE000) == ADTS_AAC_DES_EXIST)
			STRCPY(str_audio_type, "AAC");
		else
			MEMSET(str_audio_type, 0, sizeof(str_audio_type));
		
		if(str_audio_type[0] == 0)
			sprintf(str,"V %d/ A %d/ P %d",p_node.video_pid,audioPID & 0x1FFF,p_node.pcr_pid);
		else
			sprintf(str,"V %d/ A %d[%s]/ P %d",p_node.video_pid,audioPID & 0x1FFF,str_audio_type, p_node.pcr_pid);
	}
	txt = &txt_pidinfo;
	OSD_SetTextFieldContent(txt, STRING_ANSI, (UINT32)str);
    
#if (SYS_PROJECT_FE == PROJECT_FE_DVBS || SYS_PROJECT_FE == PROJECT_FE_DVBS2)

	txt = &txt_satname;
#ifndef DB_USE_UNICODE_STRING
	OSD_SetTextFieldContent(txt, STRING_ANSI, (UINT32)s_node.sat_name);
#else
	OSD_SetTextFieldContent(txt, STRING_UNICODE, (UINT32)s_node.sat_name);
#endif

//modify for program infor 2011 11 05
    if(t_node.ft_type != FRONTEND_TYPE_S)
    {//when the satellite is not DVBS, not show satellite
    
		remove_menu_item_conwithout_focus(&g_win_progdetail, (OBJECT_HEAD *)& txt_satname, 0);
		remove_menu_item_conwithout_focus(&g_win_progdetail, (OBJECT_HEAD *)& txt_string2,  TXT_H );
		//delete the item from the container
		if(TXT_T + TXT_H*2==txt_tpinfo.head.frame.uTop)
		OSD_MoveObject((POBJECT_HEAD*)&txt_tpinfo, 0, (-TXT_H), TRUE);
		if(TXT_T + TXT_H*3==txt_pidinfo.head.frame.uTop)
		OSD_MoveObject((POBJECT_HEAD*)&txt_pidinfo, 0, (-TXT_H), TRUE);
		//adjust the postion
    }
   if(t_node.ft_type == FRONTEND_TYPE_S)
   {
   		BOOL  no_remove_satname=TRUE, no_remove_string2=TRUE;
		OBJECT_HEAD* obj=OSD_GetContainerNextObj(&g_win_progdetail);
		while(obj!=NULL)
		{//linkage has txt_satname
			if((OBJECT_HEAD*)&txt_satname==obj)
				no_remove_satname=FALSE;
			obj=OSD_GetObjpNext(obj);
		}
		if(no_remove_satname)
		{//txt_satname has been removed, then add it to the container
			 txt_satname.head.pNext=OSD_GetObjpNext(((OBJECT_HEAD *)& txt_progname));
			txt_progname.head.pNext=(OBJECT_HEAD *)& txt_satname;
		}
		obj=OSD_GetContainerNextObj(&g_win_progdetail);
		while(obj!=NULL)
		{//linkage has txt_string2
			if((OBJECT_HEAD*)&txt_string2==obj)
				no_remove_string2=FALSE;
			obj=OSD_GetObjpNext(obj);
		}
		if(no_remove_string2)
		{//txt_string2 has been removed, then add it to the container
			 txt_string2.head.pNext=OSD_GetObjpNext(((OBJECT_HEAD *)& txt_string1));
			txt_string1.head.pNext=(OBJECT_HEAD *)& txt_string2;
		}
		//move down the fllowing textfield
		if(TXT_T + TXT_H==txt_string3.head.frame.uTop)
   		{
			OSD_MoveObject((POBJECT_HEAD*)&txt_string3, 0, (TXT_H), TRUE);
		}
		if(TXT_T + TXT_H*2==txt_string4.head.frame.uTop)
			OSD_MoveObject((POBJECT_HEAD*)&txt_string4, 0, (TXT_H), TRUE);
   		if(TXT_T + TXT_H==txt_tpinfo.head.frame.uTop)
   		{
			OSD_MoveObject((POBJECT_HEAD*)&txt_tpinfo, 0, (TXT_H), TRUE);
		}
		if(TXT_T + TXT_H*2==txt_pidinfo.head.frame.uTop)
			OSD_MoveObject((POBJECT_HEAD*)&txt_pidinfo, 0, (TXT_H), TRUE);
   }
//modify end

#endif  

    if(t_node.ft_type == FRONTEND_TYPE_S)
        sprintf(str,"%d/%s/%d", t_node.frq, (t_node.pol==0) ? "H" : "V",t_node.sym);
#ifdef DVBC_SUPPORT
    else if(t_node.ft_type == FRONTEND_TYPE_C)
    {
        freq_str = (void *)(display_strs[MAX_DISP_STR_ITEMS-2]);
        get_freq_str(t_node.frq, freq_str, FALSE);
        sprintf(str,"%s/%d/%s",freq_str, t_node.sym, QamTable[t_node.FEC_inner - 4]);
    }
#endif    
    else if(t_node.ft_type == FRONTEND_TYPE_T)
    {        
        FFT = "";
        if (t_node.FFT == 2)
            FFT = "2K";
        else if (t_node.FFT == 8)
            FFT = "8K";
        else if (t_node.FFT == 1)
            FFT = "1K";
        else if (t_node.FFT == 4)
            FFT = "4K";
        else if (t_node.FFT == 16)
            FFT = "16K";
        else if (t_node.FFT == 32)
            FFT = "32K";
        
        modulation = "";
        if (t_node.modulation == 2)
            modulation = "DQPSK";
        else if (t_node.modulation == 4)
            modulation = "QPSK";
        else if (t_node.modulation == 16)
            modulation = "16QAM";
        else if (t_node.modulation == 64)
            modulation = "64QAM";
        else if (t_node.modulation == (64+1))
            modulation = "256QAM";
        
	//modify for program infor Transponder more "//"
        //sprintf(str,"%dKHz/%s/%s", t_node.frq, FFT, modulation);
        sprintf(str,"%dKHZ",t_node.frq);
	if(""!=FFT)
		{
		strcat(str,"/");
		strcat(str,FFT);
		}
	if(""!=modulation)
		{
		strcat(str,"/");
		strcat(str,modulation);
		}
    }
    
	txt = &txt_tpinfo;
	OSD_SetTextFieldContent(txt, STRING_ANSI, (UINT32)str);
	
	txt = &txt_progname;
#ifndef DB_USE_UNICODE_STRING
	OSD_SetTextFieldContent(txt, STRING_ANSI, (UINT32)p_node.service_name);
#else
	OSD_SetTextFieldContent(txt, STRING_UNICODE, (UINT32)p_node.service_name);
#endif
	txt = &txt_string4;
	OSD_SetTextFieldContent(txt, STRING_ANSI, (UINT32)"PID");
}
#if defined(SUPPORT_VMX_STD) || defined(SUPPORT_VMX)
//add a function to handle pin checking window open after prog detail window opened
extern void progdetail_win_close()
{
	OSD_ClearObject((POBJECT_HEAD)&g_win_progdetail, C_UPDATE_ALL);
	menu_stack_pop();
}
#endif	
